<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>This指向</title>
  </head>
  <body>
    <script>
      /**
       * 1.this是什吗?
       *   - 任何函数本质上都是通过某个对象来调用的，如果没有直接指定的就是window
       *   - 所有函数内部都有一个变量this,他的值是调用函数的当前对象
       *
       * 2.this指向问题
       *   参考博客：https://www.cnblogs.com/wymbk/p/9299710.html
       * - this 就是函数运行时所在的环境对象，谁调用就指向谁,没调用就指向window，当出现箭头函数内的，就指向宿主元素。
       *  情况 1：以函数的形式调用时，this 是 window； - _ test()
       *  情况 2：以方法的形式调用时，this 就是调用方法的对象； -_ obj.test()
       *  情况 3：以构造函数的形式调用时，this 就是实例化的对象；- new test()
       *  情况 4：apply, call, bind 调用：this 指向就是这些函数的第一个参数; -_ p.call(obj)
       * */

      //1. this指向window
      function myFnc() {
        console.log(this);
      }
      myFnc(); //window,     此时，因为没有调用者，所以this默认指向最顶层也就是window

      //2. this指向调用方法的对象
      var myObj = {
        myVal: 3,
        myFnc: function () {
          console.log(this);
        },
      };
      myObj.myFnc(); //myobj,   此时myObj调用了所以this指向于myObj;

      //3. apply, call, bind 调用,this指向第一个参数
      function myFuc1() {
        console.log(this);
      }
      function myFnc2(a, b) {
        console.log(this);
      }
      //此时绑定的就是myFnc1，所以当前this的指向就是myFnc1;
      //call和apply的绑定机制大致是一样的，所以就不一一解释了。
      myFnc2.call(myFnc1); //myFnc1

      var myObj = {
        myFnc: function () {
          setTimtout(
            function () {
              //因为在定时器函数中，没有调用者，所以默认指向window。又因为使用bind()方法给回调函数直接绑定了当前this指向，
              //所以当前this指向就是myObj。
              console.log(this);
            }.bind(this)
          );
        },
      };
      myObj.myFnc(); //myObj

      //4. 箭头函数中的this
      var myObj = {
        myFnc: function () {
          function childFnc() {
            setTimeout(() => {
              //因为箭头函数，当前this继承于它的宿主也就是childFnc。childFnc方法的执行，
              //因为没有调用者。所以它的this指向的是window。所以当前打印的this指向就是window。
              console.log(this,'====='); //window
            });
          }
          childFnc();
        },
      };
      myObj.myFnc();
    </script>
  </body>
</html>
